

#include <cegfx/cecamera.h>


ceCamera::ceCamera (const iViewport* viewport)
	: viewport (viewport)
{
	IQF_CONSTRUCT;
	from = D3DXVECTOR3(0, 0, 100);
	at = D3DXVECTOR3(0, 0, 0);
	up = D3DXVECTOR3(0, 1, 0);
	projector = new ceProjector (viewport);
	projector->AddRef ();

	Update ();
}

ceCamera::~ceCamera ()
{
	if (projector)
	{
		projector->Release ();
	}
}

IQF_IMPLEMENTATION_BEGIN(ceCamera);
IQF_IMPLEMENTATION_END();

void ceCamera::SetViewport (const iViewport* viewport)
{
	this->viewport = viewport;
}

const iViewport* ceCamera::GetViewport () const
{
	return viewport;
}

void ceCamera::SetFrom (const D3DXVECTOR3& from)
{
	this->from = from;
}

void ceCamera::MoveFrom (const D3DXVECTOR3& amount)
{
	D3DXVec3Add (&from, &from, &amount);
}

const D3DXVECTOR3& ceCamera::GetFrom () const
{
	return from;
}

void ceCamera::SetAt (const D3DXVECTOR3& at)
{
	this->at = at;
}

void ceCamera::MoveAt (const D3DXVECTOR3& amount)
{
	D3DXVec3Add (&at, &at, &amount);
}

const D3DXVECTOR3& ceCamera::GetAt () const
{
	return at;
}

void ceCamera::SetUp (const D3DXVECTOR3& up)
{
	this->up = up;
}

const D3DXVECTOR3& ceCamera::GetUp () const
{
	return up;
}

void ceCamera::Update ()
{
	D3DXMatrixLookAtLH (&matrix, &from, &at, &up);
}

const D3DXMATRIX& ceCamera::GetMatrix () const
{
	return matrix;
}


ceProjector* ceCamera::GetProjector ()
{
	return projector;
}

const ceProjector* ceCamera::GetProjector () const
{
	return projector;
}

#define VEC3(v4) D3DXVECTOR3(v4.x, v4.y, v4.z)

void ceCamera::SetupClipper (ceClipper* clipper) const
{
	float l = projector->GetLeft ();
	float r = projector->GetRight ();
	float b = projector->GetBottom ();
	float t = projector->GetTop ();
	float n = projector->GetNear ();

	// create the 5 points defining the frustum
	D3DXVECTOR4 c (0, 0, 0, 1);
	D3DXVECTOR4 lt (l, t, n, 1);
	D3DXVECTOR4 rt (r, t, n, 1);
	D3DXVECTOR4 lb (l, b, n, 1);
	D3DXVECTOR4 rb (r, b, n, 1);

	D3DXMATRIX inv;
	float det; D3DXMatrixDeterminant (&matrix);
	D3DXMatrixInverse (&inv, &det, &matrix);

	// transform them into global space
	D3DXVec4Transform (&c, &c, &inv);
	D3DXVec4Transform (&lt, &lt, &inv);
	D3DXVec4Transform (&rt, &rt, &inv);
	D3DXVec4Transform (&lb, &lb, &inv);
	D3DXVec4Transform (&rb, &rb, &inv);

	clipper->AddPlane (VEC3 (c), VEC3 (lt), VEC3 (lb));
	clipper->AddPlane (VEC3 (c), VEC3 (lb), VEC3 (rb));
	clipper->AddPlane (VEC3 (c), VEC3 (rb), VEC3 (rt));
	clipper->AddPlane (VEC3 (c), VEC3 (rt), VEC3 (lt));
};
